import { Destroyable, react, reactJson, Event, track, HasOwner, reactJsonWithUndefined } from "earthsdk3";
import { MyProjectManager } from "../MyProjectManager";
import { ObjResettingWithEvent } from "earthsdk3";
import { reqCloneMaterial, reqDeleteMaterial, reqRenameMaterial, reqUpdateMaterial } from "@/api";
import { ElMessage } from "element-plus";
import loading from "@/api/loading";
import { MaterialEditing } from "./materialEditing";
import { ESRtsFeatureEditing } from "earthsdk3";
import { getsceneObjNumfromSceneTree } from "../utils";
import { CzmES3DTileset } from "earthsdk3-cesium";

const selectmagfilter = [
    {
        type: 'NEAREST',
        value: 9728
    },
    {
        type: 'LINEAR',
        value: 9729
    },


]

const selectminfilter = [
    {
        type: 'NEAREST',
        value: 9728
    },
    {
        type: 'LINEAR',
        value: 9729
    },
    {
        type: 'NEAREST_MIPMAP_NEAREST',
        value: 9984
    },
    {
        type: 'LINEAR_MIPMAP_NEAREST',
        value: 9985
    },
    {
        type: 'NEAREST_MIPMAP_LINEAR',
        value: 9986
    },
    {
        type: 'LINEAR_MIPMAP_LINEAR',
        value: 9987
    }

]

class absorbResettting extends Destroyable {
    constructor(materailsManager: MaterailsManager, owner: MyProjectManager) {
        super();
        const viewer = owner.activeViewer
        const eSRtsTileset = owner.cimrtsManager.eSRtsTileset
        if (!viewer) return;

        this.dispose(viewer.clickEvent.don(async e => {
            if (!e.screenPosition) return;
            const pick1 = await viewer.pick(e.screenPosition);
            const sceneObject = pick1?.sceneObject;
            if (!sceneObject) return;
            if ((sceneObject.id !== eSRtsTileset.id) && (sceneObject.typeName != "ESRtsFeatureEditing")) return;

            let pick2: any
            // 第二次拾取
            if (sceneObject.typeName == "ESRtsTileset") {
                // @ts-ignore
                sceneObject.es3DTileset.featureIdLabel = 1
                pick2 = await viewer.pick(e.screenPosition);
                // @ts-ignore
                sceneObject.es3DTileset.featureIdLabel = 0
            } else {
                // @ts-ignore
                sceneObject.featureIdLabel = 1
                pick2 = await viewer.pick(e.screenPosition);
                // @ts-ignore
                sceneObject.featureIdLabel = 0
            }
            console.log("pick2", pick2);

            const materialName = pick2?.tilesetPickInfo?.materialName
            if (!materialName) {
                ElMessage.warning('该要素无材质')
                return;

            }
            const flag = materailsManager.materailsLists.find((item: any) => item.id == materialName)
            if (flag) {
                materailsManager.currentMaterial = materailsManager.materailsLists.find((item: any) => item.id == materialName)
                // 滚动到目标行
                materailsManager.scrollToRow()
            } else {
                ElMessage.warning('该要素材质已被删除')
                materailsManager.currentMaterial = {}
            }
        }))

    }
}

class pickResettting extends Destroyable {
    constructor(materailsManager: MaterailsManager, owner: MyProjectManager) {
        super();
        const viewer = owner.activeViewer
        const eSRtsTileset = owner.cimrtsManager.eSRtsTileset
        if (!viewer) return;
        this.dispose(viewer.clickEvent.don(async e => {
            if (!e.screenPosition) return;
            // 拾取
            const obj = await eSRtsTileset.pickFeature(viewer, e.screenPosition)
            // 选中的id
            const currentFeatureId = obj?.featureId

            if (this.isDestroyed() || !currentFeatureId) return;

            const property = await eSRtsTileset.getFeatureProperty(currentFeatureId) as any;
            if (!property.geometry.materials || !property.geometry.materials.length) {
                ElMessage.warning('该要素无材质')
                return;
            }
            const materials = property.geometry.materials
            const flag = materailsManager.materailsLists.find((item: any) => item.id == materials[0])
            if (flag) {
                materailsManager.pickMaterial = materailsManager.materailsLists.find((item: any) => item.id == materials[0])
                console.log("pickMaterial", materailsManager.pickMaterial);

            } else {
                ElMessage.warning('已吸取的材质不存在于材质列表')
                materailsManager.pickMaterial = {}
            }
        }))
    }
}



export class MaterailsManager extends HasOwner<MyProjectManager> {

    get es3DTileset() { return this.owner.cimrtsManager.eSRtsTileset.es3DTileset }

    // 材质列表
    private _materailsLists = this.dv(react<any>([]));
    get materailsLists() { return this._materailsLists.value; }
    set materailsLists(value) { this._materailsLists.value = value }
    get materailsListsChanged() { return this._materailsLists.changed; }

    // 标记点击
    private _isHighlight = this.dv(react<string>(""));
    get isHighlight() { return this._isHighlight.value; }
    set isHighlight(value) { this._isHighlight.value = value }
    get isHighlightChanged() { return this._isHighlight.changed; }

    // 材质编辑器拾取
    private _isPick = this.dv(react<boolean>(false));
    get isPick() { return this._isPick.value; }
    set isPick(value) { this._isPick.value = value }
    get isPickChanged() { return this._isPick.changed; }

    // 选中的材质
    private _currentMaterial = this.dv(react<any>({}));
    get currentMaterial() { return this._currentMaterial.value; }
    set currentMaterial(value) { this._currentMaterial.value = value }
    get currentMaterialChanged() { return this._currentMaterial.changed; }

    // 拾取的材质
    private _pickMaterial = this.dv(react<any>({}));
    get pickMaterial() { return this._pickMaterial.value; }
    set pickMaterial(value) { this._pickMaterial.value = value }
    get pickMaterialChanged() { return this._pickMaterial.changed; }

    // 定位的参数
    private _scrollParam = this.dv(react<any>({
        currentIndex: -1,
        currentRow: 0,
        containerWidth: 0,
        itemWidth: 90,
        itemHeight: 123,
        itemsPerRow: 4
    }));
    get scrollParam() { return this._scrollParam.value; }
    set scrollParam(value) { this._scrollParam.value = value }
    get scrollParamChanged() { return this._scrollParam.changed; }

    private _container: any = null;
    get container() { return this._container; }
    set container(value) { this._container = value }

    // 材质拖拽事件
    private _dragEvent = this.dv(new Event<[string, DragEvent, string]>());
    get dragEvent() { return this._dragEvent; }

    // 吸取处理
    private _absorbResettting = this.dv(new ObjResettingWithEvent(this.isHighlightChanged, (res) => {
        if (!this.isHighlight) {
            return undefined
        }

        if (this.isHighlight == 'absorb') {

            return new absorbResettting(this, this.owner);
        } else {
            // this.owner.cimrtsManager.eSRtsTileset.es3DTileset.featureIdLabel = 0
            return undefined
        }

    }))
    get absorbResettting() { return this._absorbResettting; }

    // 材质编辑器 拾取处理
    private _pickResettting = this.dv(new ObjResettingWithEvent(this.isPickChanged, (res) => {
        if (!this.isPick) {
            return undefined
        } else {
            return new pickResettting(this, this.owner);
        }
    }))
    get pickResettting() { return this._pickResettting; }

    private _timer: any = null
    get timer() { return this._timer; }
    set timer(value: any) { this._timer = value; }

    // 获取材质列表
    async getMaterialList() {
        try {
            await this.owner.cimrtsManager.getOneTileService()
            const tileServiceInfo = this.owner.cimrtsManager.tileServiceInfo;
            this.materailsLists = tileServiceInfo.materials ? tileServiceInfo.materials : [];
        } catch (error) {
            console.log(error)
        }
    }

    // 重命名材质
    async renameMaterial(param: any) {
        try {
            const res = await reqRenameMaterial(param)
            // @ts-ignore
            if (res.status !== 'ok') return;
            ElMessage.success('重命名材质成功')
        } catch (error) {
            console.log(error)
        }
    }

    // 克隆材质
    async cloneMaterial(param: any) {
        try {
            const res = await reqCloneMaterial(param)
            // @ts-ignore
            if (res.status !== 'ok') return;
            ElMessage.success('克隆材质成功')
        } catch (error) {
            console.log(error)
        }
    }

    // 编辑材质
    async updateMaterial(param: any) {
        try {
            const res = await reqUpdateMaterial(param)
            // @ts-ignore
            if (res.status !== 'ok') {
                loading.closeLoading()
                return;
            }
            ElMessage.success('编辑材质成功')
            loading.closeLoading()

        } catch (error) {
            loading.closeLoading()
            console.log(error)
        }
    }

    // 删除材质
    async deleteMaterial(param: any) {
        try {
            const res = await reqDeleteMaterial(param)
            // @ts-ignore
            if (res.status !== 'ok') return;
            ElMessage.success('删除材质成功')
        } catch (error) {
            console.log(error)
        }
    }

    // 计算容器宽度
    initResizeObserver(containerRef: HTMLElement) {
        return new Promise((resolve, reject) => {
            if (!containerRef) {
                return reject(new Error('容器元素不存在'));
            }
            this.container = containerRef;

            // 超时保险（3秒未响应则报错）
            const timeoutId = setTimeout(() => {
                observer.unobserve(containerRef);
                reject(new Error('容器尺寸获取超时'));
            }, 3000);

            const observer = new ResizeObserver((entries) => {
                // 过滤无效回调（当容器实际尺寸变化时才处理）
                if (entries[0].contentRect.width > 0) {
                    clearTimeout(timeoutId);
                    this.scrollParam.containerWidth = entries[0].contentRect.width;

                    console.log('容器宽度已获取:', this.scrollParam.containerWidth);

                    // 计算每行元素数量
                    this.scrollParam.itemsPerRow = Math.floor(this.scrollParam.containerWidth / this.scrollParam.itemWidth);
                    console.log('每行元素个数:', this.scrollParam.itemsPerRow);

                    resolve(this.scrollParam.containerWidth);
                }
            });

            // 立即触发一次观察（获取初始值）
            observer.observe(containerRef);
        });
    };

    // 滚动到目标行
    scrollToRow() {
        // 计算当前索引
        this.scrollParam.currentIndex = this.materailsLists.findIndex((item: any) => item.id == this.currentMaterial.id)
        // 目标行
        this.scrollParam.currentRow = Math.floor(this.scrollParam.currentIndex / this.scrollParam.itemsPerRow)
        // 滚动距离
        const scrollTop = this.scrollParam.currentRow * this.scrollParam.itemHeight
        this.container.scrollTo({ top: scrollTop, behavior: 'smooth' })
    }

    async setMaterail(sceneObject: ESRtsFeatureEditing, data: any, materialName: string) {
        const param = JSON.parse(data.param);
        const uiMaterial: any = {
            baseColorFactor: param.baseColorFactor,
            metallicFactor: param.metallicFactor,
            roughnessFactor: param.roughnessFactor,
            doubleSided: param.doubleSided,
            unlit: param.unlit,
            alphaMode: param.alphaMode,
            magFilter: selectmagfilter.find((item) => item.value == param.sampler[0])?.type,
            minFilter: selectminfilter.find((item) => item.value == param.sampler[1])?.type,
        }
        if (param.baseColorTexture) {
            uiMaterial.baseColorTexture = {
                value: `${this.owner.cimrtsManager.cimrtsIp}/ds/featuretiles/${data.dataset}/${param.baseColorTexture}`,
                offset: param.baseTextureTranslate,
                scale: param.baseTextureScale,
                rotate: param.baseTextureRotate,
            }
        }
        uiMaterial.normalTexture = param.normalTexture != "" ? {
            value: `${this.owner.cimrtsManager.cimrtsIp}/ds/featuretiles/${data.dataset}/${param.normalTexture}`,
            offset: param.normalTextureTranslate,
            scale: param.normalTextureScale,
            rotate: param.normalTextureRotate,
        } : undefined

        console.log("场景对象材质参数", uiMaterial);
        await sceneObject.setMaterial("default")
        if (this.timer) clearInterval(this.timer)

        this.timer = setTimeout(async () => {
            const option: any = {}
            option[materialName] = { ...uiMaterial }
            const res = await sceneObject.setMaterial(option)
            if (res.type == "warn") {
                ElMessage({
                    message: "部分材质颜色纹理设置失败，请检查原始模型中材质是否具有baseColorTexture属性",
                    type: 'warning',
                })
            }
        }, 100)
        // requestAnimationFrame(async () => {
        //     const option: any = {}
        //     option[materialName] = { ...uiMaterial }
        //     const res = await sceneObject.setMaterial(option)
        //     if (res.type == "warn") {
        //         ElMessage({
        //             message: "部分材质颜色纹理设置失败，请检查原始模型中材质是否具有baseColorTexture属性",
        //             type: 'warning',
        //         })
        //     }
        // })

        // @ts-ignore
        sceneObject.materialOptions = { ...data }

        // const serverMaterial: any = {
        //     baseColorFactor: {
        //         enable: param.baseColorFactor ? true : false,
        //         value: param.baseColorFactor
        //     },
        //     metallicFactor: {
        //         enable: param.metallicFactor ? true : false,
        //         value: param.metallicFactor
        //     },
        //     doubleSided: {
        //         enable: param.doubleSided ? true : false,
        //         value: param.doubleSided
        //     },
        //     unlit: {
        //         enable: param.unlit ? true : false,
        //         value: param.unlit
        //     },
        //     alphaMode: {
        //         enable: param.alphaMode ? true : false,
        //         value: param.alphaMode
        //     },
        //     magFilter: {
        //         enable: (param.sampler && param.sampler.length) ? true : false,
        //         value: param.sampler[0]
        //     },
        //     minFilter: {
        //         enable: (param.sampler && param.sampler.length) ? true : false,
        //         value: param.sampler[1]
        //     },
        //     baseColorTexture: {
        //         "enable": param.baseColorTexture ? true : false,
        //         "value": param.baseColorTexture ? param.baseColorTexture : "",
        //         "translate": (param.baseTextureTranslate && param.baseTextureTranslate.length) ? param.baseTextureTranslate : [0, 0],
        //         "scale": (param.baseTextureScale && param.baseTextureScale.length) ? param.baseTextureScale : [1, 1],
        //         "rotate": param.baseTextureRotate ? param.baseTextureRotate : 0,
        //     },
        //     normalTexture: {
        //         "enable": param.normalTexture ? true : false,
        //         "value": param.normalTexture ? param.normalTexture : "",
        //         "translate": (param.normalTextureTranslate && param.normalTextureTranslate.length) ? param.normalTextureTranslate : [0, 0],
        //         "scale": (param.normalTextureScale && param.normalTextureScale.length) ? param.normalTextureScale : [1, 1],
        //         "rotate": param.normalTextureRotate ? param.normalTextureRotate : 0
        //     }
        // }
        // console.log("后端材质参数", serverMaterial);

        // sceneObject.beautifyMaterails = { ...serverMaterial }

        sceneObject.changeMaterial = {
            oldMaterialId: materialName,
            newMaterialId: data.id
        }

        console.log("后端材质参数", sceneObject.changeMaterial);

    }


    async init() {
        await this.getMaterialList()
    }


    // 清除参数
    clear() {
        this.isHighlight = ""
        this.currentMaterial = {}
        this.scrollParam = {
            currentIndex: -1,
            currentRow: 0,
            containerWidth: 0,
            itemWidth: 90,
            itemHeight: 123,
            itemsPerRow: 4
        }
        this.container = null
        this.isPick = false
        this.pickMaterial = {}
        if (this.timer) clearInterval(this.timer)

    }

    constructor(private _tileServiceName: string, owner: MyProjectManager) {
        super(owner);
        const eSRtsTileset = owner.cimrtsManager.eSRtsTileset
        const viewer = owner.activeViewer

        if (!viewer) return;

        this.dispose(this.dragEvent.don(async (type, dragEvent, paramStr) => {
            if (type == "scene") {
                // 第一次拾取
                const pick1 = await eSRtsTileset.pickFeature(viewer, [dragEvent.x, dragEvent.y])

                // 选中的id
                const currentFeatureId = pick1?.featureId
                // console.log("pick1", pick1);

                if (this.isDestroyed() || !currentFeatureId) return;
                let sceneObject: ESRtsFeatureEditing | undefined = undefined

                if (!(owner.cimrtsSceneTreeWrapper?.getTreeItemFromSceneObjId(currentFeatureId))) {
                    sceneObject = owner.createSceneObject(ESRtsFeatureEditing, currentFeatureId) as ESRtsFeatureEditing
                    // @ts-ignore
                    await sceneObject.init(eSRtsTileset, currentFeatureId)

                    const treeItem = owner.createdTreeItem(owner.cimrtsSceneTreeWrapper)
                    treeItem.sceneObject = sceneObject;
                    const name = pick1.pickInnerFields.name
                    const newName = "材质管理_" + (name ? name : (sceneObject.id ? sceneObject.id : ""))
                    const num = getsceneObjNumfromSceneTree(sceneObject.typeName, owner.cimrtsSceneTreeWrapper)
                    treeItem.name = `${newName}(${num})`
                    owner.cimrtsSceneTreeWrapper?.uiTree.clearAllSelectedItems()
                    treeItem.uiTreeObject.selected = true

                    const don = sceneObject.d(sceneObject.tilesetReady.donce((tileset) => {
                        const a = tileset.allTilesLoaded.addEventListener(async () => {
                            if (!sceneObject) return;
                            // 第二次拾取
                            sceneObject.featureIdLabel = 1
                            const pick2 = await viewer.pick([dragEvent.x, dragEvent.y])
                            sceneObject.featureIdLabel = 0

                            // 选中的materialName
                            const materialName = pick2?.tilesetPickInfo?.materialName
                            // console.log("pick2", pick2);
                            // @ts-ignore
                            this.setMaterail(sceneObject, JSON.parse(paramStr), materialName)
                            a()
                            don();
                        })
                    }));
                } else {

                    sceneObject = owner.getSceneObjectById(currentFeatureId) as ESRtsFeatureEditing
                    // 第二次拾取
                    sceneObject.featureIdLabel = 1
                    const pick2 = await viewer.pick([dragEvent.x, dragEvent.y])
                    sceneObject.featureIdLabel = 0

                    // 选中的materialName
                    const materialName = pick2?.tilesetPickInfo?.materialName
                    this.setMaterail(sceneObject, JSON.parse(paramStr), materialName)
                }
            }

        }))
    }
}